/**
 * Du an danh co shogi online duoc phat trien boi Le Thanh Nghi
 * thuoc cong ty N&N.,Inc
 */
package at.com.vn.chess.util;

import java.awt.Rectangle;
import java.util.ArrayList;

import vn.nnn.shogi.board.Board;
import vn.nnn.shogi.quanco.QV;
import vn.nnn.shogi.quanco.QuanCo;

/**
 * @author nghilt
 * 2011/10/01
 */
public class CommonMethod {
	public static ArrayList<QuanCo> cloneListQuanCo( ArrayList<QuanCo> listQuanCo ) {
		ArrayList<QuanCo> newListQuanCo = new ArrayList<QuanCo>();
		QuanCo newQuanCo;		
		try {
			for( QuanCo quanCo : listQuanCo ) {
				newQuanCo = ( QuanCo ) quanCo.clone();
				newListQuanCo.add( newQuanCo );
			}
		} catch ( CloneNotSupportedException e ) {
			throw new RuntimeException();
		}		
		return newListQuanCo;
	}
	
	public static QV findQuanVua( ArrayList<QuanCo> listQuanCo, int color ) {		
		QuanCo quanCo;
		for( int i = 0; i < listQuanCo.size(); i++ ) {
			quanCo = listQuanCo.get( i );
			if ( quanCo instanceof QV && quanCo.color == color ) {
				return ( QV ) quanCo;				
			}
		}
		
		return null;
	}
	

	public static QuanCo findQuanCoInList( ArrayList<QuanCo> listQuanCo, Rectangle toaDo ) {
		QuanCo quanCo;
		for( int i = 0; i < listQuanCo.size(); i++ ) {
			quanCo = listQuanCo.get( i );
			if ( quanCo.toaDo == toaDo ) {
				return quanCo;				
			}
		}
		
		return null;
	}
	

	public static int findQuanCoPositionInList( ArrayList<QuanCo> dummyList,
			Rectangle dest ) {
		int foundedIdx = Const.UNDEFINE_VALUE;
		for ( int i = 0; i < dummyList.size(); i++ ) {
			if ( ( dummyList.get( i ).isInSelectedArea( dest ) ) ) {
				foundedIdx = i;
			}
		}
		return foundedIdx;
	}
	
	public static boolean isHetCo( Board board, ArrayList<QuanCo> listQuanCo, int whichSide ) {
		
		QV quanVua = CommonMethod.findQuanVua( listQuanCo, whichSide );
		
		// Tim quan dang chieu
		QuanCo quanDangChieu;
		
		// Neu khong phai la dang bi chieu
		if( !quanVua.isDangBiChieu( board, listQuanCo ) ) {
			return false;
		}			
		
		// Neu dang bi chieu thi tim xem co nuoc chay khong
		ArrayList<Rectangle> allPosibleMovement = quanVua.findAllPosibleMovement( board, listQuanCo );
		ArrayList<QuanCo> dummyList;
		QV dummyVua;
		
		for( Rectangle dest : allPosibleMovement ) {
			dummyList = cloneListQuanCo( listQuanCo );
			dummyVua = CommonMethod.findQuanVua( dummyList, whichSide );
			
			// Tim xem co quan nao dang dung o vi tri muon di den hay khong
			int foundedIdx = CommonMethod.findQuanCoPositionInList( dummyList, dest );
			
			// Di chuyen den
			dummyVua.move( board, dest, foundedIdx, dummyList );
			
			// Chi can di chuyen den cho khong bi chieu thi van chua het co
			if( !dummyVua.isDangBiChieu( board, dummyList )) {
				return false;
			}
		}			

		// Kiem tra xem quan dang chieu co the bi an mat hay khong
		// Neu an xong ma het tinh trang bi chieu thi chua het co
		dummyList = cloneListQuanCo( listQuanCo );
		dummyVua = CommonMethod.findQuanVua( dummyList, whichSide );
		quanDangChieu = dummyVua.findQuanDangChieu( board, dummyList );
		for( QuanCo dumQuanCo : dummyList ) {
			if( dumQuanCo.color == quanVua.color ) {
				if( dumQuanCo.canMove( board, quanDangChieu.toaDo, quanDangChieu, dummyList ) ) {
					
					int foundedIdx = quanDangChieu.getPositionInList( dummyList );
					
					// Thu an quan dang chieu
					dumQuanCo.move( board, quanDangChieu.toaDo, foundedIdx, dummyList );
					
					// Neu khong con bi chieu nua thi chua het co
					if( !dummyVua.isDangBiChieu( board, dummyList ) ) {
						return false;	
					}						
				}
			}
		}
		
		// Tim toan bo nuoc co the di cua quan dang chieu
		// ( bao gom ca nuoc di ma co quan minh dang dung san o do )
		quanDangChieu = quanVua.findQuanDangChieu( board, listQuanCo );
		allPosibleMovement = quanDangChieu.findAllPosibleMovement( board, listQuanCo );
		
		// Thu di chuyen tat ca cac quan den vi tri do va kiem tra xem co con bi chieu hay khong
		// Tim tat ca cac quan cua ben dang bi chieu co tren ban co
		// Lay ra toan bo index cua cac quan do
		ArrayList<Integer> listQuanDangBiChieuIdx = new ArrayList<Integer>();
		QuanCo quanCo;
		for( int i = 0; i < listQuanCo.size(); i ++ ) {
			quanCo = listQuanCo.get( i );
			if( quanCo.color == quanVua.color && !quanCo.isTuBinh ) {
				listQuanDangBiChieuIdx.add( i );
			}
		}

		
		// Voi moi quan, di den toan bo nhung nuoc co the di cua quan dang chieu
		// sau do kiem tra xem quan minh co con bi chieu hay khong
		// Neu chi can mot nuoc di ma quan minh khong bi chieu thi chua het co
		QuanCo dummyQuanCoTheDi;
		QuanCo dummyFoundedPiece;
		int dummyFoundedIdx;
		for( Integer idx : listQuanDangBiChieuIdx ) {			
			for( Rectangle dest : allPosibleMovement ) {
				dummyList = cloneListQuanCo( listQuanCo );
				dummyQuanCoTheDi = dummyList.get( idx );				
				
				dummyFoundedPiece = CommonMethod.findQuanCoInList( dummyList, dest );
				dummyFoundedIdx = CommonMethod.findQuanCoPositionInList( dummyList, dest );
				if( dummyQuanCoTheDi.canMove( board, dest, dummyFoundedPiece, dummyList ) ) {
					dummyQuanCoTheDi.move( board, dest, dummyFoundedIdx, dummyList );
					
					dummyVua = CommonMethod.findQuanVua( dummyList, whichSide );
					
					// Chi can di chuyen den cho khong bi chieu thi van chua het co
					if( !dummyVua.isDangBiChieu( board, dummyList )) {
						return false;
					}
				}
			}
		}

		return true;
	}
	
	public static int switchColor( int orgColor ) {
		if( orgColor == QuanCo.QUAN_DEN ) {
			return QuanCo.QUAN_TRANG;
		}else {
			return QuanCo.QUAN_DEN;
		}
	}
	
	public static ArrayList<QuanCo> makeSymmetryListQuanCo( Board board, ArrayList<QuanCo> listQuanCo ) {
		ArrayList<QuanCo> newListQuanCo = new ArrayList<QuanCo>();
		for( QuanCo quanCo : listQuanCo ) {
			Rectangle rect = quanCo.toaDo;
			rect = board.makeSymmetry( rect );
			
			quanCo.setToaDo( rect );
			newListQuanCo.add( quanCo );
		}
		
		return newListQuanCo;
	}
	
	/**
	 * Ham lay so la tam cua mot day so lien tuc
	 * @param start
	 * @param end
	 * @return
	 */
	public static int getMiddlePoint( int start, int end ) {
		int length = 0;
		
		if( ( end + start ) % 2 == 0 ) {
			length = end + start; 
		}else {
			length = end + start + 1;
		}
		
		return length / 2;		
	}
	
	public static int getSymmetricPoint( int point, int start, int end ) {
		int middlePoint = getMiddlePoint( start, end );
		int symmetricPoint = 0;
		
		if( ( end + start ) % 2 == 0 ) {
			symmetricPoint = 2 * middlePoint - point;
		}else {
			symmetricPoint = 2 * middlePoint - point - 1;
		}
		
		return symmetricPoint;
	}
}
